package com.kk.xhr.model.service.impl;

import com.kk.xhr.common.pojo.BinaryEnum;
import com.kk.xhr.model.dao.RoleDynamicSqlSupport;
import com.kk.xhr.model.dao.RoleMapper;
import com.kk.xhr.model.dao.UserRoleDynamicSqlSupport;
import com.kk.xhr.model.dao.UserRoleMapper;
import com.kk.xhr.model.dto.PageDto;
import com.kk.xhr.model.entity.Role;
import com.kk.xhr.model.entity.UserRole;
import com.kk.xhr.model.service.IRoleService;
import lombok.RequiredArgsConstructor;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.springframework.stereotype.Repository;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.mybatis.dynamic.sql.SqlBuilder.equalTo;
import static org.mybatis.dynamic.sql.SqlBuilder.insertMultiple;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
import static org.mybatis.dynamic.sql.select.SelectDSL.select;


/**
 * 角色服务接口实现
 *
 * @author kkmystery
 * @version 1.0 2021/3/9
 * @since 1.0.0
 */
@Repository
@RequiredArgsConstructor
public class RoleServiceImpl implements IRoleService {
    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<Role> queryRolesByUserId(Long userId) {
        SelectStatementProvider selectStatementProvider = select(RoleDynamicSqlSupport.role.allColumns())
            .from(RoleDynamicSqlSupport.role, "r")
            .join(UserRoleDynamicSqlSupport.userRole, "ur")
            .on(RoleDynamicSqlSupport.id, equalTo(UserRoleDynamicSqlSupport.roleId))
            .where(UserRoleDynamicSqlSupport.userId, isEqualTo(userId))
            .and(RoleDynamicSqlSupport.status, isEqualTo((byte) 1))
            .build()
            .render(RenderingStrategies.MYBATIS3);
        return new HashSet<>(roleMapper.selectMany(selectStatementProvider));
    }


    @Override
    public PageDto<Role> query() {
        List<Role> roles = roleMapper.select(dsl -> dsl
            .where(RoleDynamicSqlSupport.status, isEqualTo(BinaryEnum.TRUE.getValue())));
        return new PageDto<>(roles.size(), roles);
    }

    @Override
    public boolean modify(Long id, String name, String nameZh, Integer order) {
        return 1 == roleMapper.updateByPrimaryKeySelective(
            new Role()
                .withId(id)
                .withName(name)
                .withNameZh(nameZh)
                .withOrder(order));
    }

    @Override
    public boolean modifyStatus(Long id, BinaryEnum status) {
        return 1 == roleMapper.updateByPrimaryKeySelective(new Role().withId(id).withStatus(status.getValue()));
    }

    @Override
    public Long add(Role role) {
        roleMapper.insertSelective(role);
        return role.getId();
    }

    @Override
    public void addUserRole(Long userId, List<Long> roleIds) {
        List<UserRole> list = roleIds
            .stream()
            .map(roleId -> new UserRole().withUserId(userId).withRoleId(roleId))
            .collect(Collectors.toList());
        if (roleIds.isEmpty()){
            return;
        }
        MultiRowInsertStatementProvider<UserRole> multiRowInsert = insertMultiple(list)
            .into(UserRoleDynamicSqlSupport.userRole)
            .map(UserRoleDynamicSqlSupport.userId).toProperty("userId")
            .map(UserRoleDynamicSqlSupport.roleId).toProperty("roleId")
            .build()
            .render(RenderingStrategies.MYBATIS3);
        userRoleMapper.insertMultiple(multiRowInsert);
    }

    @Override
    public void deleteUserRole(Long userId) {
        userRoleMapper.delete(dsl -> dsl
            .where(UserRoleDynamicSqlSupport.userId, isEqualTo(userId)));
    }

    @Override
    public void deleteLeaderRole(Long userId) {
        userRoleMapper.delete(dsl -> dsl
            .where(UserRoleDynamicSqlSupport.userId, isEqualTo(userId))
            .and(UserRoleDynamicSqlSupport.roleId, isEqualTo(2L)));
    }
}
